Sensor Fusion for Kinetis MCUs (ISSDK/KSDK version)
output_stream.c File Reference
+ Include dependency graph for output_stream.c:

Go to the source code of this file.

Macros

#define MAXPACKETRATEHZ   40
 
#define RATERESOLUTION   1000
 

Functions

void sBufAppendItem (uint8_t *pDest, uint16_t *pIndex, uint8_t *pSource, uint16_t iBytesToCopy)
 
void sBufAppendZeros (uint8_t *pDest, uint16_t *pIndex, uint16_t numZeros)
 
void readCommon (SV_ptr data, Quaternion *fq, int16_t *iPhi, int16_t *iThe, int16_t *iRho, int16_t iOmega[], uint16_t *isystick)
 
uint16_t throttle ()
 
void CreateAndSendPackets (SensorFusionGlobals *sfg, uint8_t *sUARTOutputBuffer)
 

Macro Definition Documentation

#define MAXPACKETRATEHZ   40

Definition at line 38 of file output_stream.c.

Referenced by throttle().

#define RATERESOLUTION   1000

Definition at line 39 of file output_stream.c.

Referenced by throttle().

Function Documentation

void CreateAndSendPackets ( SensorFusionGlobals sfg,
uint8_t *  sUARTOutputBuffer 
)

Called once per fusion cycle to stream information required by the NXP Sensor Fusion Toolbox. Packet protocols are defined in the NXP Sensor Fusion for Kinetis Product Development Kit User Guide.

Definition at line 144 of file output_stream.c.

Referenced by initializeControlPort().

145 {
146  Quaternion fq; // quaternion to be transmitted
147  float ftmp; // scratch
148  static uint32_t iTimeStamp = 0; // 1MHz time stamp
149  uint16_t iIndex; // output buffer counter
150  int32_t scratch32; // scratch int32_t
151  int16_t scratch16; // scratch int16_t
152  int16_t iPhi,
153  iThe,
154  iRho; // integer angles to be transmitted
155  int16_t iDelta; // magnetic inclination angle if available
156  int16_t iOmega[3]; // scaled angular velocity vector
157  uint16_t isystick; // algorithm systick time
158  int16_t i, j, k; // general purpose
159  uint8_t tmpuint8_t; // scratch uint8_t
160  uint8_t flags; // byte of flags
161  uint8_t AngularVelocityPacketOn,
162  DebugPacketOn,
163  RPCPacketOn;
164  int8_t AccelCalPacketOn;
165  static uint8_t iPacketNumber = 0; // packet number
166 
167  // update the 1MHz time stamp counter expected by the PC GUI (independent of project clock rates)
168  iTimeStamp += 1000000 / FUSION_HZ;
169 
170 #if (MAXPACKETRATEHZ < FUSION_HZ)
171  uint8_t skip_packet = throttle(); // possible UART bandwidth problem
172  if (skip_packet) return; // need to skip packet transmission to avoid UART overrun
173 #endif
174 
175  // cache local copies of control flags so we don't have to keep dereferencing pointers below
176  quaternion_type quaternionPacketType;
177  quaternionPacketType = sfg->pControlSubsystem->QuaternionPacketType;
178  AngularVelocityPacketOn = sfg->pControlSubsystem->AngularVelocityPacketOn;
179  DebugPacketOn = sfg->pControlSubsystem->DebugPacketOn;
180  RPCPacketOn = sfg->pControlSubsystem->RPCPacketOn;
181  AccelCalPacketOn = sfg->pControlSubsystem->AccelCalPacketOn;
182 
183  // zero the counter for bytes accumulated into the transmit buffer
184  iIndex = 0;
185 
186  // ************************************************************************
187  // Main type 1: range 0 to 35 = 36 bytes
188  // Debug type 2: range 0 to 7 = 8 bytes
189  // Angular velocity type 3: range 0 to 13 = 14 bytes
190  // Euler angles type 4: range 0 to 13 = 14 bytes
191  // Altitude/Temp type 5: range 0 to 13 = 14 bytes
192  // Magnetic type 6: range 0 to 16 = 18 bytes
193  // Kalman packet 7: range 0 to 47 = 48 bytes
194  // Precision Accelerometer packet 8: range 0 to 46 = 47 bytes
195  //
196  // Total excluding intermittent packet 8 is:
197  // 152 bytes vs 256 bytes size of sUARTOutputBuffer
198  // at 25Hz, data rate is 25*152 = 3800 bytes/sec = 38.0kbaud = 33% of 115.2kbaud
199  // at 40Hz, data rate is 40*152 = 6080 bytes/sec = 60.8kbaud = 53% of 115.2kbaud
200  // at 50Hz, data rate is 50*152 = 7600 bytes/sec = 76.0kbaud = 66% of 115.2kbaud
201  // ************************************************************************
202  // ************************************************************************
203  // fixed length packet type 1
204  // this packet type is always transmitted
205  // total size is 0 to 35 equals 36 bytes
206  // ************************************************************************
207  // [0]: packet start byte (need a iIndex++ here since not using sBufAppendItem)
208  sUARTOutputBuffer[iIndex++] = 0x7E;
209 
210  // [1]: packet type 1 byte (iIndex is automatically updated in sBufAppendItem)
211  tmpuint8_t = 0x01;
212  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
213 
214  // [2]: packet number byte
215  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
216  iPacketNumber++;
217 
218  // [6-3]: 1MHz time stamp (4 bytes)
219  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iTimeStamp, 4);
220 
221  // [12-7]: integer accelerometer data words (scaled to 8192 counts per g for PC GUI)
222  // send non-zero data only if the accelerometer sensor is enabled and used by the selected quaternion
223  if (sfg->iFlags & F_USING_ACCEL) {
224  switch (quaternionPacketType)
225  {
226  case Q3:
227  case Q6MA:
228  case Q6AG:
229  case Q9:
230 #if F_USING_ACCEL
231  // accelerometer data is used for the selected quaternion so transmit but clip at 4g
232  scratch32 = (sfg->Accel.iGc[CHX] * 8192) / sfg->Accel.iCountsPerg;
233  if (scratch32 > 32767) scratch32 = 32767;
234  if (scratch32 < -32768) scratch32 = -32768;
235  scratch16 = (int16_t) (scratch32);
236  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
237 
238  scratch32 = (sfg->Accel.iGc[CHY] * 8192) / sfg->Accel.iCountsPerg;
239  if (scratch32 > 32767) scratch32 = 32767;
240  if (scratch32 < -32768) scratch32 = -32768;
241  scratch16 = (int16_t) (scratch32);
242  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
243 
244  scratch32 = (sfg->Accel.iGc[CHZ] * 8192) / sfg->Accel.iCountsPerg;
245  if (scratch32 > 32767) scratch32 = 32767;
246  if (scratch32 < -32768) scratch32 = -32768;
247  scratch16 = (int16_t) (scratch32);
248  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
249  break;
250 #endif // F_USING_ACCEL
251  case Q3M:
252  case Q3G:
253  default:
254  // accelerometer data is not used in currently selected algorithm so transmit zero
255  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
256  break;
257  }
258  } else {
259  // accelerometer structure is not defined so transmit zero
260  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
261  }
262  // [18-13]: integer calibrated magnetometer data words (already scaled to 10 count per uT for PC GUI)
263  // send non-zero data only if the magnetometer sensor is enabled and used by the selected quaternion
264  if (sfg->iFlags & F_USING_MAG)
265  switch (quaternionPacketType)
266  {
267  case Q3M:
268  case Q6MA:
269  case Q9:
270 #if F_USING_MAG
271  // magnetometer data is used for the selected quaternion so transmit
272  scratch16 = (int16_t) (sfg->Mag.iBc[CHX] * 10) / (sfg->Mag.iCountsPeruT);
273  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
274  scratch16 = (int16_t) ((sfg->Mag.iBc[CHY] * 10) / sfg->Mag.iCountsPeruT);
275  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
276  scratch16 = (int16_t) ((sfg->Mag.iBc[CHZ] * 10) / sfg->Mag.iCountsPeruT);
277  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
278  break;
279 #endif
280  // magnetometer data is not used in currently selected algorithm so transmit zero
281  case Q3:
282  case Q3G:
283  case Q6AG:
284  default:
285  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
286  break;
287  }
288  else
289  {
290  // magnetometer structure is not defined so transmit zero
291  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
292  }
293 
294  // [24-19]: uncalibrated gyro data words (scaled to 20 counts per deg/s for PC GUI)
295  // send non-zero data only if the gyro sensor is enabled and used by the selected quaternion
296  if (sfg->iFlags & F_USING_GYRO)
297  {
298  switch (quaternionPacketType)
299  {
300  case Q3G:
301  case Q6AG:
302 #if F_USING_GYRO
303  case Q9:
304 
305  // gyro data is used for the selected quaternion so transmit
306  scratch16 = (int16_t) ((sfg->Gyro.iYs[CHX] * 20) / sfg->Gyro.iCountsPerDegPerSec);
307  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
308  scratch16 = (int16_t) ((sfg->Gyro.iYs[CHY] * 20) / sfg->Gyro.iCountsPerDegPerSec);
309  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
310  scratch16 = (int16_t) ((sfg->Gyro.iYs[CHZ] * 20) / sfg->Gyro.iCountsPerDegPerSec);
311  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
312  break;
313 #endif
314  case Q3:
315  case Q3M:
316  case Q6MA:
317  default:
318  // gyro data is not used in currently selected algorithm so transmit zero
319  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
320  break;
321  }
322  }
323  else
324  {
325  // gyro structure is not defined so transmit zero
326  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
327  }
328 
329  // initialize default quaternion, flags byte, angular velocity and orientation
330  fq.q0 = 1.0F;
331  fq.q1 = fq.q2 = fq.q3 = 0.0F;
332  flags = 0x00;
333  iOmega[CHX] = iOmega[CHY] = iOmega[CHZ] = 0;
334  iPhi = iThe = iRho = iDelta = 0;
335  isystick = 0;
336 
337  // flags byte 33: quaternion type in least significant nibble
338  // Q3: coordinate nibble, 1
339  // Q3M: coordinate nibble, 6
340  // Q3G: coordinate nibble, 3
341  // Q6MA: coordinate nibble, 2
342  // Q6AG: coordinate nibble, 4
343  // Q9: coordinate nibble, 8
344  // flags byte 33: coordinate in most significant nibble
345  // Aerospace/NED: 0, quaternion nibble
346  // Android: 1, quaternion nibble
347  // Windows 8: 2, quaternion nibble
348  // set the quaternion, flags, angular velocity and Euler angles
349  switch (quaternionPacketType)
350  {
351 #if F_3DOF_G_BASIC
352  case Q3:
353  if (sfg->iFlags & F_3DOF_G_BASIC)
354  {
355  flags |= 0x01;
356  readCommon((SV_ptr)&sfg->SV_3DOF_G_BASIC, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
357  }
358  break;
359 #endif
360 #if F_3DOF_B_BASIC
361  case Q3M:
362  if (sfg->iFlags & F_3DOF_B_BASIC)
363  {
364  flags |= 0x06;
365  readCommon((SV_ptr)&sfg->SV_3DOF_B_BASIC, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
366  }
367  break;
368 #endif
369 #if F_3DOF_Y_BASIC
370  case Q3G:
371  if (sfg->iFlags & F_3DOF_Y_BASIC)
372  {
373  flags |= 0x03;
374  readCommon((SV_ptr)&sfg->SV_3DOF_Y_BASIC, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
375  }
376  break;
377 #endif
378 #if F_6DOF_GB_BASIC
379  case Q6MA:
380  if (sfg->iFlags & F_6DOF_GB_BASIC)
381  {
382  flags |= 0x02;
383  iDelta = (int16_t) (10.0F * sfg->SV_6DOF_GB_BASIC.fLPDelta);
384  readCommon((SV_ptr)&sfg->SV_6DOF_GB_BASIC, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
385  }
386  break;
387 #endif
388 #if F_6DOF_GY_KALMAN
389  case Q6AG:
390  if (sfg->iFlags & F_6DOF_GY_KALMAN)
391  {
392  flags |= 0x04;
393  readCommon((SV_ptr)&sfg->SV_6DOF_GY_KALMAN, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
394  }
395  break;
396 #endif
397 #if F_9DOF_GBY_KALMAN
398  case Q9:
399  if (sfg->iFlags & F_9DOF_GBY_KALMAN)
400  {
401  flags |= 0x08;
402  iDelta = (int16_t) (10.0F * sfg->SV_9DOF_GBY_KALMAN.fDeltaPl);
403  readCommon((SV_ptr)&sfg->SV_9DOF_GBY_KALMAN, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
404  }
405  break;
406 #endif
407  default:
408  // use the default data already initialized
409  break;
410  }
411 
412  // [32-25]: scale the quaternion (30K = 1.0F) and add to the buffer
413  scratch16 = (int16_t) (fq.q0 * 30000.0F);
414  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
415  scratch16 = (int16_t) (fq.q1 * 30000.0F);
416  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
417  scratch16 = (int16_t) (fq.q2 * 30000.0F);
418  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
419  scratch16 = (int16_t) (fq.q3 * 30000.0F);
420  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
421 
422  // set the coordinate system bits in flags from default NED (00)
423 #if THISCOORDSYSTEM == ANDROID
424  // set the Android flag bits
425  flags |= 0x10;
426 #elif THISCOORDSYSTEM == WIN8
427  // set the Win8 flag bits
428  flags |= 0x20;
429 #endif // THISCOORDSYSTEM
430 
431  // [33]: add the flags byte to the buffer
432  sBufAppendItem(sUARTOutputBuffer, &iIndex, &flags, 1);
433 
434  // [34]: add the shield (bits 7-5) and Kinetis (bits 4-0) byte
435  tmpuint8_t = ((THIS_SHIELD & 0x07) << 5) | (THIS_BOARD & 0x1F);
436  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
437 
438  // [35]: add the tail byte for the standard packet type 1
439  sUARTOutputBuffer[iIndex++] = 0x7E;
440 
441  // ************************************************************************
442  // Variable length debug packet type 2
443  // total size is 0 to 7 equals 8 bytes
444  // ************************************************************************
445  if (DebugPacketOn)
446  {
447  // [0]: packet start byte
448  sUARTOutputBuffer[iIndex++] = 0x7E;
449 
450  // [1]: packet type 2 byte
451  tmpuint8_t = 0x02;
452  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
453 
454  // [2]: packet number byte
455  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
456  iPacketNumber++;
457 
458  // [4-3] software version number
459  scratch16 = THISBUILD;
460  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
461 
462  // [6-5] systick count / 20
463  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &isystick, 2);
464 
465  // [7 in practice but can be variable]: add the tail byte for the debug packet type 2
466  sUARTOutputBuffer[iIndex++] = 0x7E;
467  }
468 
469  // ************************************************************************
470  // Angular Velocity packet type 3
471  // total bytes for packet type 2 is range 0 to 13 = 14 bytes
472  // ************************************************************************
473  if (AngularVelocityPacketOn)
474  {
475  // [0]: packet start byte
476  sUARTOutputBuffer[iIndex++] = 0x7E;
477 
478  // [1]: packet type 3 byte (angular velocity)
479  tmpuint8_t = 0x03;
480  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
481 
482  // [2]: packet number byte
483  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
484  iPacketNumber++;
485 
486  // [6-3]: time stamp (4 bytes)
487  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iTimeStamp, 4);
488 
489  // [12-7]: add the scaled angular velocity vector to the output buffer
490  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iOmega[CHX], 2);
491  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iOmega[CHY], 2);
492  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iOmega[CHZ], 2);
493 
494  // [13]: add the tail byte for the angular velocity packet type 3
495  sUARTOutputBuffer[iIndex++] = 0x7E;
496  }
497 
498  // ************************************************************************
499  // Roll, Pitch, Compass Euler angles packet type 4
500  // total bytes for packet type 4 is range 0 to 13 = 14 bytes
501  // ************************************************************************
502  if (RPCPacketOn)
503  {
504  // [0]: packet start byte
505  sUARTOutputBuffer[iIndex++] = 0x7E;
506 
507  // [1]: packet type 4 byte (Euler angles)
508  tmpuint8_t = 0x04;
509  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
510 
511  // [2]: packet number byte
512  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
513  iPacketNumber++;
514 
515  // [6-3]: time stamp (4 bytes)
516  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iTimeStamp, 4);
517 
518  // [12-7]: add the angles (resolution 0.1 deg per count) to the transmit buffer
519  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iPhi, 2);
520  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iThe, 2);
521  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iRho, 2);
522 
523  // [13]: add the tail byte for the roll, pitch, compass angle packet type 4
524  sUARTOutputBuffer[iIndex++] = 0x7E;
525  }
526 
527  // ************************************************************************
528  // Altitude / Temperature packet type 5
529  // total bytes for packet type 5 is range 0 to 13 = 14 bytes
530  // ************************************************************************
531 #if F_USING_PRESSURE
532  if (sfg->iFlags & F_1DOF_P_BASIC)
533  {
534  if (sfg->pControlSubsystem->AltPacketOn && sfg->Pressure.iWhoAmI)
535  {
536  // [0]: packet start byte
537  sUARTOutputBuffer[iIndex++] = 0x7E;
538 
539  // [1]: packet type 5 byte
540  tmpuint8_t = 0x05;
541  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
542 
543  // [2]: packet number byte
544  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
545  iPacketNumber++;
546 
547  // [6-3]: time stamp (4 bytes)
548  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iTimeStamp,
549  4);
550 
551  // [10-7]: altitude (4 bytes, metres times 1000)
552  scratch32 = (int32_t) (sfg->SV_1DOF_P_BASIC.fLPH * 1000.0F);
553  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch32, 4);
554 
555  // [12-11]: temperature (2 bytes, deg C times 100)
556  scratch16 = (int16_t) (sfg->SV_1DOF_P_BASIC.fLPT * 100.0F);
557  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
558 
559  // [13]: add the tail byte for the altitude / temperature packet type 5
560  sUARTOutputBuffer[iIndex++] = 0x7E;
561  }
562  }
563 #endif
564 
565  // ************************************************************************
566  // magnetic buffer packet type 6
567  // currently total size is 0 to 17 equals 18 bytes
568  // this packet is only transmitted if a magnetic algorithm is computed
569  // ************************************************************************
570 #if F_USING_MAG
571  static int16_t MagneticPacketID = 0; // magnetic packet number
572  if (sfg->iFlags & F_USING_MAG)
573  {
574  // [0]: packet start byte
575  sUARTOutputBuffer[iIndex++] = 0x7E;
576 
577  // [1]: packet type 6 byte
578  tmpuint8_t = 0x06;
579  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
580 
581  // [2]: packet number byte
582  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
583  iPacketNumber++;
584 
585  // [4-3]: number of active measurements in the magnetic buffer
587  (uint8_t *) &(sfg->MagBuffer.iMagBufferCount), 2);
588 
589  // [6-5]: fit error (%) with resolution 0.01%
590  if (sfg->MagCal.fFitErrorpc > 327.67F)
591  scratch16 = 32767;
592  else
593  scratch16 = (int16_t) (sfg->MagCal.fFitErrorpc * 100.0F);
594  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
595 
596  // [8-7]: geomagnetic field strength with resolution 0.1uT
597  scratch16 = (int16_t) (sfg->MagCal.fB * 10.0F);
598  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
599 
600  // always calculate magnetic buffer row and column (low overhead and saves warnings)
601  k = MagneticPacketID - 10;
602  j = k / MAGBUFFSIZEX;
603  i = k - j * MAGBUFFSIZEX;
604 
605  // [10-9]: int16_t: ID of magnetic variable to be transmitted
606  // ID 0 to 4 inclusive are magnetic calibration coefficients
607  // ID 5 to 9 inclusive are for future expansion
608  // ID 10 to (MAGBUFFSIZEX=12) * (MAGBUFFSIZEY=24)-1 or 10 to 10+288-1 are magnetic buffer elements
609  // where the convention is used that a negative value indicates empty buffer element (index=-1)
610  if ((MagneticPacketID >= 10) && (sfg->MagBuffer.index[i][j] == -1))
611  {
612  // use negative ID to indicate inactive magnetic buffer element
613  scratch16 = -MagneticPacketID;
614  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
615  }
616  else
617  {
618  // use positive ID unchanged for variable or active magnetic buffer entry
619  scratch16 = MagneticPacketID;
620  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
621  }
622 
623  // [12-11]: int16_t: variable 1 to be transmitted this iteration
624  // [14-13]: int16_t: variable 2 to be transmitted this iteration
625  // [16-15]: int16_t: variable 3 to be transmitted this iteration
626  switch (MagneticPacketID)
627  {
628  case 0:
629  // item 1: currently unused
630  scratch16 = 0;
631  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
632 
633  // item 2: currently unused
634  scratch16 = 0;
635  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
636 
637  // item 3: magnetic inclination angle with resolution 0.1 deg
638  scratch16 = iDelta;
639  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
640  break;
641 
642  case 1:
643  // items 1 to 3: hard iron components range -3276uT to +3276uT encoded with 0.1uT resolution
644  scratch16 = (int16_t) (sfg->MagCal.fV[CHX] * 10.0F);
645  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
646  scratch16 = (int16_t) (sfg->MagCal.fV[CHY] * 10.0F);
647  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
648  scratch16 = (int16_t) (sfg->MagCal.fV[CHZ] * 10.0F);
649  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
650  break;
651 
652  case 2:
653  // items 1 to 3: diagonal soft iron range -32. to +32. encoded with 0.001 resolution
654  scratch16 = (int16_t) (sfg->MagCal.finvW[CHX][CHX] * 1000.0F);
655  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
656  scratch16 = (int16_t) (sfg->MagCal.finvW[CHY][CHY] * 1000.0F);
657  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
658  scratch16 = (int16_t) (sfg->MagCal.finvW[CHZ][CHZ] * 1000.0F);
659  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
660  break;
661 
662  case 3:
663  // items 1 to 3: off-diagonal soft iron range -32. to +32. encoded with 0.001 resolution
664  scratch16 = (int16_t) (sfg->MagCal.finvW[CHX][CHY] * 1000.0F);
665  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
666  scratch16 = (int16_t) (sfg->MagCal.finvW[CHX][CHZ] * 1000.0F);
667  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
668  scratch16 = (int16_t) (sfg->MagCal.finvW[CHY][CHZ] * 1000.0F);
669  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
670  break;
671 
672  case 4:
673  case 5:
674  case 6:
675  case 7:
676  case 8:
677  case 9:
678  // cases 4 to 9 inclusive are for future expansion so transmit zeroes for now
679  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
680  break;
681 
682  default:
683  // 10 and upwards: this handles the magnetic buffer elements
685  (uint8_t *) &(sfg->MagBuffer.iBs[CHX][i][j]), 2);
687  (uint8_t *) &(sfg->MagBuffer.iBs[CHY][i][j]), 2);
689  (uint8_t *) &(sfg->MagBuffer.iBs[CHZ][i][j]), 2);
690  break;
691  }
692 
693  // wrap the variable ID back to zero if necessary
694  MagneticPacketID++;
695  if (MagneticPacketID >= (10 + MAGBUFFSIZEX * MAGBUFFSIZEY))
696  MagneticPacketID = 0;
697 
698  // [17]: add the tail byte for the magnetic packet type 6
699  sUARTOutputBuffer[iIndex++] = 0x7E;
700  }
701 #endif
702 
703  // *******************************************************************************
704  // Kalman filter packet type 7
705  // total bytes for packet type 7 is range 0 to 41 inclusive = 42 bytes
706  // this packet is only transmitted when a Kalman algorithm is computed
707  // and then non-zero data is transmitted only when a Kalman quaternion is selected
708  // *******************************************************************************
709  bool kalman = false;
710 #if F_6DOF_GY_KALMAN
711  uint8_t six_axis_kalman = (sfg->iFlags & F_6DOF_GY_KALMAN) && (quaternionPacketType == Q6AG);
712  kalman = six_axis_kalman;
713 #endif
714 #if F_9DOF_GBY_KALMAN
715  uint8_t nine_axis_kalman = (sfg->iFlags & F_9DOF_GBY_KALMAN) && (quaternionPacketType == Q9);
716  kalman = kalman | nine_axis_kalman;
717 #endif
718 #if F_6DOF_GY_KALMAN || F_9DOF_GBY_KALMAN
719  if (kalman)
720  {
721  if ((quaternionPacketType == Q6AG) || (quaternionPacketType == Q9))
722  {
723  // [0]: packet start byte
724  sUARTOutputBuffer[iIndex++] = 0x7E;
725 
726  // [1]: packet type 7 byte
727  tmpuint8_t = 0x07;
728  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
729 
730  // [2]: packet number byte
731  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
732  iPacketNumber++;
733 
734  // [4-3]: fzgErr[CHX] resolution scaled by 30000
735  // [6-5]: fzgErr[CHY] resolution scaled by 30000
736  // [8-7]: fzgErr[CHZ] resolution scaled by 30000
737  for (i = CHX; i <= CHZ; i++)
738  {
739 #if F_6DOF_GY_KALMAN
740  if (six_axis_kalman) scratch16 = (int16_t) (sfg->SV_6DOF_GY_KALMAN.fZErr[i] * 30000.0F);
741 #endif
742 #if F_9DOF_GBY_KALMAN
743  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fZErr[i] * 30000.0F);
744 #endif
745  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16,2);
746  }
747 
748  // [10-9]: fgErrPl[CHX] resolution scaled by 30000
749  // [12-11]: fgErrPl[CHY] resolution scaled by 30000
750  // [14-13]: fgErrPl[CHZ] resolution scaled by 30000
751  for (i = CHX; i <= CHZ; i++)
752  {
753 #if F_6DOF_GY_KALMAN
754  if (six_axis_kalman) scratch16 = (int16_t) (sfg->SV_6DOF_GY_KALMAN.fqgErrPl[i] * 30000.0F);
755 #endif
756 #if F_9DOF_GBY_KALMAN
757  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fqgErrPl[i] * 30000.0F);
758 #endif
759  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16,2);
760  }
761 
762  // [16-15]: fzmErr[CHX] resolution scaled by 30000
763  // [18-17]: fzmErr[CHY] resolution scaled by 30000
764  // [20-19]: fzmErr[CHZ] resolution scaled by 30000
765  for (i = CHX; i <= CHZ; i++)
766  {
767 #if F_6DOF_GY_KALMAN
768  if (six_axis_kalman) scratch16 = 0;
769 #endif
770 #if F_9DOF_GBY_KALMAN
771  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fZErr[i + 3] * 30000.0F);
772 #endif
773  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
774  }
775 
776  // [22-21]: fmErrPl[CHX] resolution scaled by 30000
777  // [24-23]: fmErrPl[CHY] resolution scaled by 30000
778  // [26-25]: fmErrPl[CHZ] resolution scaled by 30000
779  for (i = CHX; i <= CHZ; i++)
780  {
781 #if F_6DOF_GY_KALMAN
782  if (six_axis_kalman) scratch16 = 0;
783 #endif
784 #if F_9DOF_GBY_KALMAN
785  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fqmErrPl[i] * 30000.0F);
786 #endif
787  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
788  }
789 
790  // [28-27]: fbPl[CHX] resolution 0.001 deg/sec
791  // [30-29]: fbPl[CHY] resolution 0.001 deg/sec
792  // [32-31]: fbPl[CHZ] resolution 0.001 deg/sec
793  for (i = CHX; i <= CHZ; i++)
794  {
795 #if F_6DOF_GY_KALMAN
796  if (six_axis_kalman) scratch16 = (int16_t) (sfg->SV_6DOF_GY_KALMAN.fbPl[i] * 1000.0F);
797 #endif
798 #if F_9DOF_GBY_KALMAN
799  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fbPl[i] * 1000.0F);
800 #endif
801  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
802  }
803 
804  // [34-33]: fDeltaPl resolution 0.01deg
805  scratch16 = 0;
806 #if F_9DOF_GBY_KALMAN
807  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fDeltaPl * 100.0F);
808 #endif
809  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
810 
811  // [36-35]: fAccGl[CHX] resolution 1/8192 g
812  // [38-37]: fAccGl[CHY] resolution 1/8192 g
813  // [40-39]: fAccGl[CHZ] resolution 1/8192 g
814  for (i = CHX; i <= CHZ; i++)
815  {
816  // default to zero data
817  ftmp = 0.0F;
818 #if F_6DOF_GY_KALMAN
819  if (six_axis_kalman) ftmp = sfg->SV_6DOF_GY_KALMAN.fAccGl[i] * 8192.0F;
820 #endif
821 #if F_9DOF_GBY_KALMAN
822  if (nine_axis_kalman) ftmp = sfg->SV_9DOF_GBY_KALMAN.fAccGl[i] * 8192.0F;
823 #endif
824 
825  // check for clipping
826  if (ftmp > 32767.0F) scratch16 = 32767;
827  else if (ftmp < -32768.0F) scratch16 = -32768;
828  else scratch16 = (int16_t) ftmp;
829  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
830  }
831 
832  // [42-41]: fDisGl[CHX] resolution 0.01m
833  // [44-43]: fDisGl[CHY] resolution 0.01m
834  // [46-45]: fDisGl[CHZ] resolution 0.01m
835  for (i = CHX; i <= CHZ; i++)
836  {
837  // default to zero data
838  ftmp = 0.0F;
839 #if F_9DOF_GBY_KALMAN
840  if (nine_axis_kalman) ftmp = sfg->SV_9DOF_GBY_KALMAN.fDisGl[i] * 100.0F;
841 #endif
842 
843  // check for clipping
844  if (ftmp > 32767.0F) scratch16 = 32767;
845  else if (ftmp < -32768.0F) scratch16 = -32768;
846  else scratch16 = (int16_t) ftmp;
847  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
848  }
849 
850  // [47]: add the tail byte for the Kalman packet type 7
851  sUARTOutputBuffer[iIndex++] = 0x7E;
852  }
853  } // end of check for Kalman packet
854 #endif
855 #if F_USING_ACCEL
856  // *************************************************************************
857  // fixed length packet type 8 transmitted whenever a precision accelerometer
858  // measurement has been stored.
859  // total size is 0 to 40 equals 41 bytes
860  // *************************************************************************
861  // check to see which packet (if any) is to be transmitted
862  if (AccelCalPacketOn != -1)
863  {
864  // [0]: packet start byte (need a iIndex++ here since not using sBufAppendItem)
865  sUARTOutputBuffer[iIndex++] = 0x7E;
866 
867  // [1]: packet type 8 byte (iIndex is automatically updated in sBufAppendItem)
868  tmpuint8_t = 0x08;
869  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
870 
871  // [2]: packet number byte
872  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
873  iPacketNumber++;
874 
875  // [3]: AccelCalPacketOn in range 0-11 denotes stored location and MAXORIENTATIONS denotes transmit
876  // precision accelerometer calibration on power on before any measurements have been obtained.
878  (uint8_t *) &(AccelCalPacketOn), 1);
879 
880  // [9-4]: stored accelerometer measurement fGs (scaled to 8192 counts per g)
881  if ((AccelCalPacketOn >= 0) &&
882  (AccelCalPacketOn < MAX_ACCEL_CAL_ORIENTATIONS))
883  {
884  scratch16 = (int16_t) (sfg->AccelBuffer.fGsStored[AccelCalPacketOn][CHX] * 8192.0F);
885  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
886  scratch16 = (int16_t) (sfg->AccelBuffer.fGsStored[AccelCalPacketOn][CHY] * 8192.0F);
887  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
888  scratch16 = (int16_t) (sfg->AccelBuffer.fGsStored[AccelCalPacketOn][CHZ] * 8192.0F);
889  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
890  }
891  else
892  {
893  // transmit zero bytes since this is the power on or reset transmission of the precision calibration
894  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
895  }
896 
897  // [15-10]: precision accelerometer offset vector fV (g scaled by 32768.0)
898  scratch16 = (int16_t) (sfg->AccelCal.fV[CHX] * 32768.0F);
899  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
900  scratch16 = (int16_t) (sfg->AccelCal.fV[CHY] * 32768.0F);
901  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
902  scratch16 = (int16_t) (sfg->AccelCal.fV[CHZ] * 32768.0F);
903  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
904 
905  // [21-16]: precision accelerometer inverse gain matrix diagonal finvW - 1.0 (scaled by 10000.0)
906  scratch16 = (int16_t) ((sfg->AccelCal.finvW[CHX][CHX] - 1.0F) * 10000.0F);
907  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
908  scratch16 = (int16_t) ((sfg->AccelCal.finvW[CHY][CHY] - 1.0F) * 10000.0F);
909  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
910  scratch16 = (int16_t) ((sfg->AccelCal.finvW[CHZ][CHZ] - 1.0F) * 10000.0F);
911  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
912 
913  // [27-22]: precision accelerometer inverse gain matrix off-diagonal finvW (scaled by 10000)
914  scratch16 = (int16_t) (sfg->AccelCal.finvW[CHX][CHY] * 10000.0F);
915  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
916  scratch16 = (int16_t) (sfg->AccelCal.finvW[CHX][CHZ] * 10000.0F);
917  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
918  scratch16 = (int16_t) (sfg->AccelCal.finvW[CHY][CHZ] * 10000.0F);
919  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
920 
921  // [33-28]: precision accelerometer rotation matrix diagonal fR0 (scaled by 10000)
922  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHX][CHX] * 10000.0F);
923  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
924  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHY][CHY] * 10000.0F);
925  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
926  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHZ][CHZ] * 10000.0F);
927  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
928 
929  // [45-34]: precision accelerometer inverse rotation matrix off-diagonal fR0 (scaled by 10000)
930  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHX][CHY] * 10000.0F);
931  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
932  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHX][CHZ] * 10000.0F);
933  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
934  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHY][CHX] * 10000.0F);
935  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
936  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHY][CHZ] * 10000.0F);
937  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
938  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHZ][CHX] * 10000.0F);
939  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
940  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHZ][CHY] * 10000.0F);
941  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
942 
943  // [46]: add the tail byte for the packet type 8
944  sUARTOutputBuffer[iIndex++] = 0x7E;
945 
946  // disable future packets of this type until a new measurement has been obtained
948  }
949 #endif // F_USING_ACCEL
950  // ********************************************************************************
951  // all packets have now been constructed in the output buffer so now transmit.
952  // The final iIndex++ gives the number of bytes to transmit which is one more than
953  // the last index in the buffer. this function is non-blocking
954  // ********************************************************************************
956  return;
957 }
enum quaternion quaternion_type
the quaternion type to be transmitted
Quaternion derived from full 9-axis sensor fusion.
Definition: sensor_fusion.h:70
#define MAGBUFFSIZEX
x dimension in magnetometer buffer (12x24 equals 288 elements)
Definition: magnetic.h:44
#define F_USING_GYRO
nominally 0x0004 if a gyro is to be used, 0x0000 otherwise
#define CHY
Used to access Y-channel entries in various data data structures.
Definition: sensor_fusion.h:77
void readCommon(SV_ptr data, Quaternion *fq, int16_t *iPhi, int16_t *iThe, int16_t *iRho, int16_t iOmega[], uint16_t *isystick)
uint32_t iFlags
a bit-field of sensors and algorithms used
float q0
scalar component
Definition: orientation.h:39
volatile uint8_t AltPacketOn
flag to enable altitude packet
Definition: control.h:70
Quaternion derived from 3-axis mag only (auto compass algorithm)
Definition: sensor_fusion.h:66
MagCalibration MagCal
mag cal storage
volatile int8_t AccelCalPacketOn
variable used to coordinate accelerometer calibration
Definition: control.h:71
float q3
z vector component
Definition: orientation.h:42
int16_t iMagBufferCount
number of magnetometer readings
Definition: magnetic.h:68
Quaternion derived from 3-axis gyro only (rotation)
Definition: sensor_fusion.h:67
int16_t iCountsPeruT
counts per uT
Quaternion derived from 3-axis accel + 3 axis mag (eCompass)
Definition: sensor_fusion.h:68
Quaternion derived from 3-axis accel + 3-axis gyro (gaming)
Definition: sensor_fusion.h:69
uint16_t throttle()
(OVERSAMPLE_RATIO * MAXPACKETRATEHZ) / SENSORFS
struct ControlSubsystem * pControlSubsystem
MagSensor Mag
magnetometer storage
quaternion structure definition
Definition: orientation.h:37
#define F_1DOF_P_BASIC
1DOF pressure (altitude) and temperature algorithm selector - 0x0100 to include, 0x0000 otherwise ...
#define F_9DOF_GBY_KALMAN
void sBufAppendItem(uint8_t *pDest, uint16_t *pIndex, uint8_t *pSource, uint16_t iBytesToCopy)
Utility function used to place data in output buffer about to be transmitted via UART.
Definition: output_stream.c:59
float finvW[3][3]
current inverse soft iron matrix
Definition: magnetic.h:76
#define THISBUILD
define build number sent in debug packet for display purposes only
float fV[3]
current hard iron offset x, y, z, (uT)
Definition: magnetic.h:75
#define F_6DOF_GY_KALMAN
6DOF accel and gyro (Kalman) algorithm selector - 0x2000 to include, 0x0000 otherwise ...
#define F_3DOF_G_BASIC
3DOF accel tilt (accel) algorithm selector - 0x0200 to include, 0x0000 otherwise
#define CHZ
uint8_t sUARTOutputBuffer[256]
main output buffer defined in control.c
Definition: control.c:59
volatile uint8_t DebugPacketOn
flag to enable debug packet
Definition: control.h:68
#define MAX_ACCEL_CAL_ORIENTATIONS
number of stored precision accelerometer measurements
int16_t iBc[3]
averaged calibrated measurement (counts)
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76
float fFitErrorpc
current fit error %
Definition: magnetic.h:79
MagBuffer MagBuffer
mag cal constellation points
writePort_t * write
low level function to write a char buffer to the serial stream
Definition: control.h:72
volatile uint8_t RPCPacketOn
flag to enable roll, pitch, compass packet
Definition: control.h:69
Quaternion derived from 3-axis accel (tilt)
Definition: sensor_fusion.h:65
#define F_3DOF_Y_BASIC
3DOF gyro integration algorithm selector - 0x0800 to include, 0x0000 otherwise
#define F_6DOF_GB_BASIC
6DOF accel and mag eCompass algorithm selector - 0x1000 to include, 0x0000 otherwise ...
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads
int32_t index[MAGBUFFSIZEX][MAGBUFFSIZEY]
array of time indices
Definition: magnetic.h:66
void sBufAppendZeros(uint8_t *pDest, uint16_t *pIndex, uint16_t numZeros)
Definition: output_stream.c:92
float fB
current geomagnetic field magnitude (uT)
Definition: magnetic.h:77
#define F_USING_ACCEL
nominally 0x0001 if an accelerometer is to be used, 0x0000 otherwise
#define MAGBUFFSIZEY
y dimension in magnetometer buffer (12x24 equals 288 elements)
Definition: magnetic.h:45
float q2
y vector component
Definition: orientation.h:41
#define F_3DOF_B_BASIC
3DOF mag eCompass (vehicle/mag) algorithm selector - 0x0400 to include, 0x0000 otherwise ...
Excluding SV_1DOF_P_BASIC, Any of the SV_ fusion structures above could be cast to type SV_COMMON for...
#define F_USING_MAG
Definition: magnetic.h:38
float q1
x vector component
Definition: orientation.h:40
int16_t iBs[3][MAGBUFFSIZEX][MAGBUFFSIZEY]
uncalibrated magnetometer readings
Definition: magnetic.h:65
volatile quaternion_type QuaternionPacketType
quaternion type transmitted over UART
Definition: control.h:66
volatile uint8_t AngularVelocityPacketOn
flag to enable angular velocity packet
Definition: control.h:67

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void readCommon ( SV_ptr  data,
Quaternion fq,
int16_t *  iPhi,
int16_t *  iThe,
int16_t *  iRho,
int16_t  iOmega[],
uint16_t *  isystick 
)

Definition at line 100 of file output_stream.c.

Referenced by CreateAndSendPackets().

106  {
107  *fq = data->fq;
108  iOmega[CHX] = (int16_t) (data->fOmega[CHX] * 20.0F);
109  iOmega[CHY] = (int16_t) (data->fOmega[CHY] * 20.0F);
110  iOmega[CHZ] = (int16_t) (data->fOmega[CHZ] * 20.0F);
111  *iPhi = (int16_t) (10.0F * data->fPhi);
112  *iThe = (int16_t) (10.0F * data->fThe);
113  *iRho = (int16_t) (10.0F * data->fRho);
114  *isystick = (uint16_t) (data->systick / 20);
115 }
float fThe
pitch (deg)
#define CHY
Used to access Y-channel entries in various data data structures.
Definition: sensor_fusion.h:77
Quaternion fq
orientation quaternion
float fOmega[3]
average angular velocity (deg/s)
float fRho
compass (deg)
#define CHZ
float fPhi
roll (deg)
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76
int32_t systick
systick timer;

+ Here is the caller graph for this function:

void sBufAppendItem ( uint8_t *  pDest,
uint16_t *  pIndex,
uint8_t *  pSource,
uint16_t  iBytesToCopy 
)

Utility function used to place data in output buffer about to be transmitted via UART.

Definition at line 59 of file output_stream.c.

Referenced by CreateAndSendPackets(), and sBufAppendZeros().

61 {
62  uint16_t i; // loop counter
63 
64  // loop over number of bytes to add to the destination buffer
65  for (i = 0; i < iBytesToCopy; i++)
66  {
67  switch (pSource[i])
68  {
69  case 0x7E:
70  // special case 1: replace 0x7E (start and end byte) with 0x7D and 0x5E
71  pDest[(*pIndex)++] = 0x7D;
72  pDest[(*pIndex)++] = 0x5E;
73  break;
74 
75  case 0x7D:
76  // special case 2: replace 0x7D with 0x7D and 0x5D
77  pDest[(*pIndex)++] = 0x7D;
78  pDest[(*pIndex)++] = 0x5D;
79  break;
80 
81  default:
82  // general case, simply add this byte without change
83  pDest[(*pIndex)++] = pSource[i];
84  break;
85  }
86  }
87 
88  return;
89 }

+ Here is the caller graph for this function:

void sBufAppendZeros ( uint8_t *  pDest,
uint16_t *  pIndex,
uint16_t  numZeros 
)

Definition at line 92 of file output_stream.c.

Referenced by CreateAndSendPackets().

92  {
93  int16_t scratch16 = 0;
94  uint16_t i;
95  for (i=0; i<numZeros; i++) {
96  sBufAppendItem(pDest, pIndex, (uint8_t *) &scratch16, 2);
97  }
98 }
void sBufAppendItem(uint8_t *pDest, uint16_t *pIndex, uint8_t *pSource, uint16_t iBytesToCopy)
Utility function used to place data in output buffer about to be transmitted via UART.
Definition: output_stream.c:59

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

uint16_t throttle ( )

(OVERSAMPLE_RATIO * MAXPACKETRATEHZ) / SENSORFS

Definition at line 119 of file output_stream.c.

Referenced by CreateAndSendPackets().

120 {
121  static int32 iThrottle = 0;
122  uint8_t skip;
123  // The UART (serial over USB and over Bluetooth)
124  // is limited to 115kbps which is more than adequate for the 31kbps
125  // needed at the default 25Hz output rate but insufficient for 100Hz or
126  // 200Hz output rates. There is little point is providing output data
127  // faster than 25Hz video rates but since the UARTs can
128  // support a higher rate, the limit is set to MAXPACKETRATEHZ=40Hz.
129 
130  // the increment applied to iThrottle is in the range 0 to (RATERESOLUTION - 1)
131  iThrottle += ((int32) MAXPACKETRATEHZ * (int32) RATERESOLUTION) / (int32) FUSION_HZ;
132  if (iThrottle >= RATERESOLUTION) {
133  // update the throttle counter and transmit the packets over UART (USB and Bluetooth)
134  iThrottle -= RATERESOLUTION;
135  skip = false;
136  } else {
137  skip = true;
138  }
139  return(skip);
140 }
int32_t int32
Definition: sensor_fusion.h:57
#define MAXPACKETRATEHZ
Definition: output_stream.c:38
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads
#define RATERESOLUTION
Definition: output_stream.c:39

+ Here is the caller graph for this function: